Перейти к основному содержимому

5.08. Типы данных и переменные

Разработчику Архитектору

Типы данных и переменные

Поскольку все типы данных здесь являются объектами, давайте их разберём.

  1. Числа. В Smalltalk числа — объекты, и с ними можно делать всё, что угодно.
42              "Integer"
3.14 "Float"
1/3 "Fraction — дробь, не потеря точности!"
16rFF "Шестнадцатеричное: 255"
2r1010 "Двоичное: 10"

Они отвечают на сообщения:

42 factorial           "→ 1405006117752879898543142606244511569936384000000000"
3.14 squared "→ 9.8596"
(1/3) * 3 "→ 1 (без потери точности!)"

Причем, 1/3 — это объект класса Fraction, а не приближённое значение. Smalltalk умеет работать с рациональными числами точно.

  1. Строки заключаются в одинарные кавычки:
'Hello, world!'
'Привет, Smalltalk!'

Строки — объекты, поддерживающие множество методов:

'hello' size                  "→ 5"
'hello' at: 1 "→ $h"
'hello' reversed "→ 'olleh'"
'hello' asUppercase "→ 'HELLO'"
'hello' includes: $e "→ true"
'hello' copyWith: $! "→ 'hello!'"

Строки изменяемы? Нет. Но можно создавать новые:

('hello' , ' world') trimBoth    "→ 'hello world'"

Оператор , — это бинарное сообщение, определённое для строк: конкатенация.

  1. Символы записываются с помощью решётки: #имя
#name
#x
#doSomething
#hello_world
#'with spaces' "можно в кавычках, если есть спецсимволы"

Чем отличается 'name' от #name?

Строка 'name'Символ #name
Изменяемый объект (в теории)Неизменяемый
Может быть много копийВ системе — только один экземпляр
Используется для текстаИспользуется как идентификатор, ключ, имя метода

Символы — как атомарные метки. Их часто используют как ключи в словарях, для отправки динамических сообщений, и в рефлексии.

  1. Логические значения: true, false, nil. Собственно, мы их уже разобрали.
(x > 0) ifTrue: [ 'positive' ] ifFalse: [ 'negative' ]
nil isNil "→ true"
true not "→ false"
false or: [ true ] "→ true"
  1. Коллекции.

Array — массив фиксированного размера:

#(1 2 3 4)                    "литерал массива"
Array with: 1 with: 2 with: 3 "создание"

OrderedCollection — динамический список:

| list |
list := OrderedCollection new.
list add: 1; add: 2; add: 3.
list removeLast.

Dictionary — ассоциативный массив (ключ → значение):

| dict |
dict := Dictionary new.
dict at: #name put: 'Alice'.
dict at: #age put: 30.
dict at: #name "→ 'Alice'"

Можно использовать символы как ключи.

Set — множество (уникальные элементы):

| set |
set := Set new.
set add: 1; add: 2; add: 1. "вторая единица не добавится"
set size "→ 2"
  1. Блоки кода.
[ 2 + 3 ]                     "блок без параметров"
[ :x | x * x ] "с одним параметром"
[ :a :b | a + b ] "с двумя"

Блоки кода могут храниться в переменных, передаваться как аргументы. выполняться через value, value:, value:value: и т.д.

В Smalltalk переменные не имеют типа. Они просто ссылаются на объекты. Переменные объявляются внутри метода, блока или скрипта с помощью вертикальных черт:

| name age total |

Это — локальные переменные.

Пример:

| name greeting |
name := 'Alice'.
greeting := 'Hello, ', name.
Transcript show: greeting.

Никаких var, let, const, int, String. Только | имена |.

Оператор присваивания — := (двоеточие + равно).

count := 0
name := 'Bob'
items := OrderedCollection new
isReady := true

:= — это синтаксис, а не сообщение. Нельзя его переопределить.

Переменные бывают нескольких видов:

Вид (тип)Область видимостиПример
ЛокальныеВ пределах метода или блока`
Параметры методаВходные аргументыdoSomething: x
ЭкземплярныеПриватные переменные объектаОбъявляются в классе: instanceVariableNames: 'name age'
КлассовыеОбщие для всех экземпляров классаclassVariableNames: 'Counter'
ГлобальныеДоступны вездеTranscript, Smalltalk, Date
СпециальныеВстроенные (self, super, true, false, nil)self doSomething

Пример объявления экземплярных переменных:

Object subclass: #Person
instanceVariableNames: 'name age'
classVariableNames: 'NextId'
package: 'MyApp'

Теперь каждый экземпляр Person будет иметь свои name и age.

Все объекты в Smalltalk происходят от Object — базового класса.

Но есть и более глубокие уровни:

  • Object — корень почти всей иерархии.
  • ProtoObject — родитель Object, имеет минимум методов.
  • Behavior — абстрактный класс для всего, что может выполнять код.
  • Class — тоже объект, экземпляр Metaclass.